#include <assertor/assertor.h>
#include <limits>
#include <string>
#include <unordered_map>
#include <vector>

using namespace kp::Assertor;

// Helper to exercise macros safely
static void
try_run(const char * title, const std::function<void()> & f)
{
    (void)title;
    try
    {
        f();
    }
    catch (const ExceptionBase &)
    {
        // swallow; policy is LogOnly so nothing should be thrown
    }
}

int
main()
{
    // Configure logging to file so emitted messages can be observed
    set_default_policy(FailurePolicy::LogOnly);
    set_log_file("kp.log", true);

    // Basic ASSERT and scalar comparison helpers
    try_run("ASSERT and ASSERT0",
            []
            {
                ASSERT(false, [] { return std::string{"forced failure"}; });
                ASSERT0(false);
            });

    try_run("Scalar compare helpers",
            []
            {
                int a = 3, b = 2;
                ASSERT_LT_SCALAR(a, b); // fail: 3 !< 2
                ASSERT_GE_SCALAR(b, a); // fail: 2 !>= 3
            });

    // ASSERT_ENSURE / ASSERT_THROW_IF core
    try_run("ASSERT_ENSURE success",
            []
            {
                ASSERT_ENSURE(false, ContractViolation, std::string{"noop"}); // fail -> log
            });

    try_run("ASSERT_THROW_IF triggers",
            []
            {
                ASSERT_THROW_IF(true, IllegalState, std::string{"idle"}); // true -> log
            });

    // Range/index convenience
    try_run("ASSERT_INDEX_IN",
            []
            {
                size_t idx = 3, size = 3;
                ASSERT_INDEX_IN(idx, size); // fail
            });

    try_run("ASSERT_IN_CLOSED_RANGE",
            []
            {
                ASSERT_IN_CLOSED_RANGE(15, 0, 10); // 失败
                ASSERT_IN_CLOSED_RANGE(-1, 0, 10); // 失败
            });

    try_run("ASSERT_IN_OPEN_RANGE",
            []
            {
                ASSERT_IN_OPEN_RANGE(0.0, 0.0, 1.0); // 失败
                ASSERT_IN_OPEN_RANGE(1.0, 0.0, 1.0); // 失败
            });

    try_run("ASSERT_SIZE_EQ/ASSERT_DIM_EQ",
            []
            {
                ASSERT_SIZE_EQ(4, 5); // 失败
                ASSERT_DIM_EQ(2, 3);  // 失败
            });

    try_run("ASSERT_NOT_EMPTY and ASSERT_HAS_KEY",
            []
            {
                std::vector<int> v{};
                ASSERT_NOT_EMPTY(v); // 失败
                std::unordered_map<std::string, int> m{};
                ASSERT_HAS_KEY(m, "key"); // 失败
            });

    try_run("ASSERT_LEN_LE", [] { ASSERT_LEN_LE(11, 10); });

    // Numeric convenience
    try_run("ASSERT_NONZERO and SCALAR checks",
            []
            {
                ASSERT_NONZERO(0); // 失败
                double x = std::numeric_limits<double>::infinity();
                ASSERT_FINITE_SCALAR(x); // 失败
            });

    // Logical/contract convenience
    try_run("ASSERT_REQUIRE/ASSERT_POST/ASSERT_UNREACHABLE/ASSERT_FEATURE_AVAILABLE",
            []
            {
                ASSERT_REQUIRE(false, "precond");            // 失败
                ASSERT_POST(false, "postcond");              // 失败
                ASSERT_FEATURE_AVAILABLE(false, "featureX"); // 失败
                ASSERT_UNREACHABLE();                        // 始终失败，仅日志
            });

    // Iterators & ranges convenience
    try_run("ASSERT_ITER_VALID/ASSERT_ITER_RANGE_VALID",
            []
            {
                ASSERT_ITER_VALID(false, "iter bad");        // 失败
                ASSERT_ITER_RANGE_VALID(false, "range bad"); // 失败
            });

    // Comparison/type convenience
    try_run("ASSERT_TYPE_EQ/ASSERT_COMPARABLE/ASSERT_ORDER",
            []
            {
                ASSERT_TYPE_EQ(false, "int", "double"); // 失败
                ASSERT_COMPARABLE(false, "a", "b");     // 失败
                ASSERT_ORDER(false, "asc", "desc");     // 失败
            });

    // I/O & filesystem convenience
    try_run("ASSERT_IO_OK/ASSERT_PERMISSION",
            []
            {
                ASSERT_IO_OK(false, "path.txt", "read fail"); // 失败
                ASSERT_PERMISSION(false, "path.txt", "read"); // 失败
            });

    // Concurrency convenience
    try_run("ASSERT_LOCKED/ASSERT_TIMEOUT_OK",
            []
            {
                ASSERT_LOCKED(false, "m", 10);       // 失败
                ASSERT_TIMEOUT_OK(false, "op", 100); // 失败
            });

    // Resource/system convenience
    try_run("ASSERT_MEMORY_AVAILABLE/ASSERT_HANDLE_VALID/ASSERT_RESOURCE_AVAILABLE",
            []
            {
                ASSERT_MEMORY_AVAILABLE(false, 1024);       // 失败
                ASSERT_HANDLE_VALID(false, "h", "invalid"); // 失败
                ASSERT_RESOURCE_AVAILABLE(false, "gpu");    // 失败
            });

    // Network convenience
    try_run("ASSERT_CONNECTED/ASSERT_PROTOCOL_OK",
            []
            {
                ASSERT_CONNECTED(false, "127.0.0.1:8080", "disconnected"); // 失败
                ASSERT_PROTOCOL_OK(false, "HTTP", "bad");                  // 失败
            });

    // Config & env convenience
    try_run("ASSERT_CONFIG_PARSED/ASSERT_CONFIG_HAS_KEY",
            []
            {
                ASSERT_CONFIG_PARSED(false, "cfg.toml", "syntax error"); // 失败
                ASSERT_CONFIG_HAS_KEY(false, "host", "server");          // 失败
            });

    // Parse/serialization convenience
    try_run("ASSERT_FORMAT_OK/ASSERT_VERSION_EQ",
            []
            {
                ASSERT_FORMAT_OK(false, "json", "format error"); // 失败
                ASSERT_VERSION_EQ("1.0", "2.0");                 // 失败
            });

    // Algorithms/data structures convenience
    try_run("ASSERT_INVARIANT/ASSERT_NO_CYCLE/ASSERT_TOPOLOGY_OK",
            []
            {
                ASSERT_INVARIANT(false, "sum>=0");              // 失败
                ASSERT_NO_CYCLE(false, "graph");                // 失败
                ASSERT_TOPOLOGY_OK(false, "G", "disconnected"); // 失败
            });

    // Direct exception construction examples
    try_run("ASSERT_SOCKET_OK/ASSERT_REQUEST_TIMEOUT_OK",
            []
            {
                ASSERT_SOCKET_OK(false, "send", -1);                   // 失败
                ASSERT_REQUEST_TIMEOUT_OK(false, "api://service", 10); // 失败
            });

    try_run("Construct ScalarOutOfRange",
            []
            {
                ASSERT_ENSURE(false,
                              ScalarOutOfRange,
                              std::string{"x:int"},
                              std::string{"42"},
                              std::string{"0"},
                              std::string{"10"}); // log
            });

    try_run("Construct IOError",
            []
            { ASSERT_IO_OK(false, std::string{"/tmp/file"}, std::string{"permission denied"}); });

    try_run("Construct DeadlockDetected",
            [] { ASSERT_NO_DEADLOCK(false, std::string{"mutexA"}, std::string{"thread-1"}); });

    try_run("Contract violation",
            [] { ASSERT_ENSURE(false, ContractViolation, std::string{"todo"}); });

    return 0;
}
